#include <linux/module.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include "led_opr.h"

#include "led_resource.h"
#include "led_opr.h"
#include "led_drv.h"

static int g_ledpins[100];
static int g_ledcnt = 0;

static int board_demo_led_init (int which) 
{
    // printk("%s %s %s %d\n", __FILE__, __FUNCTION__, __LINE__, which);

    printk("init gpio: group %d - pin %d \n", GROUP(g_ledpins[which]), PIN(g_ledpins[which]));

    switch (GROUP(g_ledpins[which]))
    {
    case 0:
        printk("init pin of group 0 ...\n");
        break;
    case 1:
        printk("init pin of group 1 ...\n");
        break;
    default:
        break;
    }
    return 0;
}

static int board_demo_led_ctl (int which, char status) 
{
    printk("set led %s: group %d, pin %d\n", status ? "on" : "off", GROUP(led_resource->pin), PIN(led_resource->pin));
    switch (GROUP(g_ledpins[which]))
    {
    case 0:
    {
        printk("set pin of group 0 ...\n");
        break;
    }
    case 1:
    {
        printk("set pin of group 1 ...\n");
        break;
    }
    default:
        break;
    }
    return 0;
}

static struct led_operations board_demo_led_opr = {
    .init = board_demo_led_init,
    .ctl = board_demo_led_ctl,
};

struct led_operations *get_board_led_opr(void) 
{
    return &board_demo_led_opr;
}

static int chip_demo_gpio_led_probe(struct platform_device *dev)
{
    struct resource *res;
    while (1)
    {
        res = platform_get_resource(dev, IORESOURCE_IRQ, i++)
        if (!res) 
        {
            break;
        }

        /* 记录引脚 */
        g_ledpins[g_ledcnt] = res->start;

        /* device create */
        led_device_create(g_ledcnt);

        g_ledcnt++;
    }

    return 0;
}

static int chip_demo_gpio_led_remove(struct platform_device *dev)
{
    struct resource *res;
    int i = 0;
    while(1) 
    {
        res = platform_get_resource(dev, IORESOURCE_IRQ, i)
        if (!res) 
        {
            break;
        }
        led_device_destory(i);
        i++;
        g_ledcnt--;
    }
    
    return 0;
}

static struct platform_driver chip_demo_gpio_drv = {
    .probe = chip_demo_gpio_led_probe,
    .remove = chip_demo_gpio_led_remove,
    .driver = {
        .name = "my_led",
    },
};

static int __init chip_demo_gpio_drv_init(void)
{
    int err;
    err = platform_driver_register(&chip_demo_gpio_drv);
    
    register_led_operations(&board_demo_led_opr);

    return 0;
}

static void __exit chip_demo_gpio_drv_exit(void)
{
    platform_driver_unregister(&chip_demo_gpio_drv);
}

module_init(chip_demo_gpio_drv_init);
module_exit(chip_demo_gpio_drv_exit);
MODULE_LICENSE("GPL");